﻿/*************************************************************************
 *
 * Copyright (c) 2009-2015 Xuld. All rights reserved.
 * 
 * Project Url: http://work.xuld.net/circus
 * 
 * This source code is part of the Project Circus.
 * 
 * This code is licensed under The Circus License.
 * See the file License.html for the license details.
 * 
 * 
 * You must not remove this notice, or any other, from this software.
 *
 * 
 *************************************************************************/


using Circus.Utility;
using System;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Web;

namespace Circus.Utility {

    /// <summary>
    /// 提供 Web 请求相关的辅助函数。
    /// </summary>
    public static class HttpHelper {

        #region Cookie

        /// <summary>
        /// 向客户端写入一个 Cookie 值。
        /// </summary>
        /// <param name="name">要写入的 Cookie 名。</param>
        /// <param name="value">要写入的 Cookie 值。</param>
        /// <returns>返回新创建的 Cookie 对象。</returns>
        public static HttpCookie setCookie(string name, string value) {
            var cookie = new HttpCookie(name, value);
            HttpContext.Current.Response.SetCookie(cookie);
            return cookie;
        }

        /// <summary>
        /// 向客户端写入一个 Cookie 值。
        /// </summary>
        /// <param name="name">要写入的 Cookie 名。</param>
        /// <param name="value">要写入的 Cookie 值。</param>
        /// <param name="expires">设置 Cookie 过期的秒数。-1 表示不过期。</param>
        /// <returns>返回新创建的 Cookie 对象。</returns>
        public static HttpCookie setCookie(string name, string value, int expires) {
            var cookie = setCookie(name, value);
            if (expires != 0) {
                cookie.Expires = expires > 0 ? DateTime.Now.AddSeconds(expires) : DateTime.MaxValue;
            }
            return cookie;
        }

        /// <summary>
        /// 删除指定的 Cookie 值。
        /// </summary>
        /// <param name="name">要删除的 Cookie 名。</param>
        /// <returns>如果删除成功则返回 true；否则返回 false。</returns>
        public static bool removeCookie(string name) {
            var cookie = HttpContext.Current.Request.Cookies[name];
            if (cookie == null) {
                return false;
            }
            cookie.Expires = DateTime.Now.AddSeconds(-1);
            HttpContext.Current.Response.SetCookie(cookie);
            return true;
        }

        /// <summary>
        /// 读取一个 Cookie 值。
        /// </summary>
        /// <param name="name">要读取的 Cookie 名。</param>
        /// <returns>返回 Cookie 对应的值。如果 Cookie 不存在，则返回 null。</returns>
        public static string getCookie(string name) {
            var cookie = HttpContext.Current.Request.Cookies.Get(name);
            if (cookie != null) {
                return cookie.Value;
            }
            return null;
        }

        #endregion

        #region IP

        /// <summary>
        /// 获取当前用户的 IP 地址。
        /// </summary>
        /// <returns></returns>
        public static string getIP() {
            var request = HttpContext.Current.Request;
            return request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.ServerVariables["HTTP_VIA"] ?? request.ServerVariables["REMOTE_ADDR"] ?? request.UserHostAddress;
        }

        #endregion

        #region JavaScript

        private const string callbackParamName = "callback";

        /// <summary>
        /// 向用户相应一个 JSONP 请求。
        /// </summary>
        /// <param name="jsonString">要响应的原始 JSON 字符串。</param>
        public static void jsonp(string jsonString) {
            var context = HttpContext.Current;
            var callback = context.Request.QueryString[callbackParamName];
            if (callback == null) {
                json(jsonString);
                return;
            }
            context.Response.ContentType = "text/javascript";
            context.Response.Write(callback);
            context.Response.Write('(');
            context.Response.Write(jsonString);
            context.Response.Write(')');
        }

        /// <summary>
        /// 向用户相应一个 JSONP 请求。
        /// </summary>
        /// <param name="content">要响应的对象。</param>
        public static void jsonp(object content) {
            var context = HttpContext.Current;
            var callback = context.Request.QueryString[callbackParamName];
            if (callback == null) {
                json(content);
                return;
            }
            context.Response.ContentType = "text/javascript";
            context.Response.Write(callback);
            context.Response.Write('(');
            writeJson(context, content);
            context.Response.Write(')');
        }

        /// <summary>
        /// 向用户相应一个 JSON 请求。
        /// </summary>
        /// <param name="jsonString">要响应的原始 JSON 字符串。</param>
        private static void json(string jsonString) {
            var context = HttpContext.Current;
            context.Response.ContentType = "application/json";
            context.Response.Write(jsonString);
        }

        /// <summary>
        /// 向用户相应一个 JSON 请求。
        /// </summary>
        /// <param name="content">要响应的对象。</param>
        private static void json(object content) {
            var context = HttpContext.Current;
            context.Response.ContentType = "application/json";
            writeJson(context, content);
        }

        private static void writeJson(HttpContext context, object content) {
            Circus.Utility.Json.JsonWriter writer = new Circus.Utility.Json.JsonWriter(context.Response.Output);
            Circus.Utility.Json.Json.currentEngine.write(writer, content);
        }

        #endregion

        #region 调试

        private static string stringify(object value) {
            var result = value == null ? "(null)" : value.ToString();
            if (result.Length == 0) {
                return "(empty)";
            }
            return result;
        }

        /// <summary>
        /// 调试输出指定变量到网页。
        /// </summary>
        /// <param name="values">要输出的变量值。</param>
        [Conditional("DEBUG")]
        public static void debug(params object[] values) {
            var response = HttpContext.Current.Response;
            foreach (var value in values) {
                string content = stringify(value);
                response.Write("<p><pre>");
                response.Write(EncodeHelper.encodeHtml(content));
                response.Write("</pre></p>");
            }
        }

        /// <summary>
        /// 调试输出指定变量到浏览器控制台。
        /// </summary>
        /// <param name="values">要输出的变量值。</param>
        [Conditional("DEBUG")]
        public static void log(params object[] values) {
            var response = HttpContext.Current.Response;
            response.Write("<script>/*From HttpHelper.log*/console.log(");
            for (int i = 0; i < values.Length; i++) {
                if (i > 0) {
                    response.Write(',');
                }
                string content = stringify(values[i]);
                response.Write('"');
                response.Write(EncodeHelper.encodeJavaScriptString(content));
                response.Write('"');
            }
            response.Write(");</script>");
        }

        /// <summary>
        /// 向客户端输出服务端全部信息。
        /// </summary>
        public static void serverInfo() {
            var context = HttpContext.Current;
            var response = context.Response;


            //response.Write("Request.Forms");
            //foreach (string c in context.Request.Form)
            //    response.Write(String.Format("{0}  =   <b>{1}</b>", c, HttpUtility.HtmlEncode(context.Request.Form[c])));

            //response.Write("Request.QueryStrings");
            //foreach (string c in context.Request.QueryString)
            //    response.Write(String.Format("{0}  =   <b>{1}</b>", c, HttpUtility.HtmlEncode(context.Request.QueryString[c])));

            //response.Write("Request.Cookies");
            //foreach (string c in context.Request.Cookies)
            //    response.Write(String.Format("{0}  =   <b>{1}</b>", c, HttpUtility.HtmlEncode(context.Request.Cookies[c].Value)));

            //response.Write("Response.Cookies");
            //foreach (string c in context.Response.Cookies)
            //    response.Write("{0}  =   <b>{1}</b>", c, HttpUtility.HtmlEncode(context.Response.Cookies[c].Value));

            //response.Write("Sessions");
            //if (context.Session != null) {
            //    foreach (string c in context.Session)
            //        response.Write("{0}  =   <b>{1}</b>", c, context.Session[c]);
            //}

            //response.Write("Applications");
            //foreach (string c in context.Application)
            //    response.Write("{0}  =   <b>{1}</b>", c, context.Application[c]);


            response.Write("<pre>");
            response.Write("Request Url: " + context.Request.RawUrl + "\r\n");
            response.Write("Physical Path: " + context.Request.PhysicalPath + "\r\n");
            response.Write("App Url: " + context.Request.ApplicationPath + "\r\n");
            response.Write("Physical App Path: " + context.Request.PhysicalApplicationPath + "\r\n");
            response.Write("IP: " + HttpHelper.getIP() + "\r\n");
            response.Write("QueryString: " + context.Request.QueryString.ToString() + "\r\n");
            response.Write("Form: " + context.Request.Form.ToString() + "\r\n");
            response.Write("Headers: " + context.Request.Headers.ToString() + "\r\n");
            response.Write("Server Variables: " + context.Request.ServerVariables.ToString() + "\r\n");
            response.Write("</pre>");
        }

        #endregion

    }

}
